package com.zlsy.secondtime.background;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author zhouliang
 * @date 2020/5/19 14:58
 * <p>
 * 第一种：运行结果出错
 * 演示计数不正确（减少），找出具体出错的位置。
 */
public class MultiThreadsError implements Runnable {

    int index = 0;
    final boolean[] marked = new boolean[1000000];
    static AtomicInteger realIndex = new AtomicInteger();
    static AtomicInteger wrongCount = new AtomicInteger();
    final Object lock = new Object();
    CyclicBarrier a = new CyclicBarrier(2);
    CyclicBarrier b = new CyclicBarrier(2);


    @Override
    public void run() {
        for (int i = 0; i < 100000; i++) {
            try {
                b.reset();
                a.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
            //index 自身++的结果
            index++;
            try {
                a.reset();
                b.await();
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
            //真正运行的次数
            realIndex.incrementAndGet();

            //判断的时候并发，导致多进来了,加了之后反而更多了？
            synchronized (lock) {
                if (marked[index] && marked[index - 1]){
                    //错误的次数 = 多了？
                    System.out.println("发生错误:" + index);
                    wrongCount.incrementAndGet();
                }
                //运行完就标记下标一次
                marked[index] = true;
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MultiThreadsError r = new MultiThreadsError();
        Thread a = new Thread(r);
        Thread b = new Thread(r);
        a.start();
        b.start();
        a.join();
        b.join();
        int index = r.index;
        System.out.println("表面上的结果：" + index);
        System.out.println("真正运行的次数：" + realIndex.get());
        System.out.println("错误次数:" + wrongCount.get());
    }
}
